package com.kuangstudy.service.pv;

import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author 飞哥
 * @Title: 学相伴出品
 * @Description: 我们有一个学习网站：https://www.kuangstudy.com
 * @date 2021/5/20 15:46
 */
@Service
@Log4j2
public class OneCacheBbsPvService {

    @Autowired
    private RedisTemplate redisTemplate;

    @PostConstruct
    public void cacheTask() {
        log.info("一级缓存cache：开始进行消费将Map中的数据刷入到二级缓存中......");
        new Thread(() -> runOneCache()).start();
    }


    /*
     * 一级缓存定时消费：
     * 定时器每个（5分钟）从jvm的内存中获取数据push进入redis的list中，
     * list存储的数据结构是每个list元素存储的是：Map<文章ID,pv数量>即每个时间块的PV数据。
     **/
    public void runOneCache() {
        while (true) {
            // 开始
            this.consumerBbsPV();
            try {
                // 每个1.5分钟执行一次同步，如果是生成环境建议是6分钟
                Thread.sleep(90000);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            log.info("一级缓存定时器消费，定时刷新开始......");
        }
    }


    /**
     * @return void
     * @Author 徐柯
     * @Description 具体每篇文章计数开始
     * @Date 15:50 2021/5/20
     * @Param [bbsid]
     **/
    public void consumerBbsPV() {
        // 1：为了方便测试，改为1分钟而已，真实环境建议5分钟
        long currentMill = System.currentTimeMillis() / (1000 * 60 * 1);
        // 2: 遍历获取一级缓存中的每个元素存入到redis中，如
        Iterator<Long> iterator = BbsPvServiceConstants.PV_MAP.keySet().iterator();
        while (iterator.hasNext()) {
            // 3:获取一级缓存中的Map数据的时间分片key
            Long cacheMillKey = iterator.next();
            //4：如果时间分片的时间小于当前时间的就存入redis的list中
            if (currentMill > cacheMillKey) {
                //5：先执行push
                Map<Integer, Integer> currentMap = BbsPvServiceConstants.PV_MAP.get(cacheMillKey);
                this.redisTemplate.opsForList().leftPush(BbsPvServiceConstants.CACHE_ONE_PV_LIST, currentMap);
                // 6: 然后从jvm删除cache，因为已经执行完毕了。可以释放了
                BbsPvServiceConstants.PV_MAP.remove(cacheMillKey);

                log.info("当前时间{}，执行的分片时间是：{}，同步到redis的list中", currentMill, cacheMillKey);
                log.info("一级缓存同步：{}", currentMap);
            }
        }
    }

}
